package Connectivity; import java.util.ArrayList; import Command.LDrawPart; import Common.Matrix4; import Common.Vector3f; import LDraw.Support.MatrixMath; import LDraw.Support.type.LDrawGridTypeT; public class Slider extends Connectivity { int startCapped; int endCapped; float length; int cylindrical; float[] spring; String tag; public int getstartCapped() { return startCapped; } public void setstartCapped(String startCapped) { this.startCapped = Integer.parseInt(startCapped); } public int getendCapped() { return endCapped; } public void setendCapped(String endCapped) { this.endCapped = Integer.parseInt(endCapped); } public float getlength() { return length; } public void setlength(String length) { this.length = Float.parseFloat(length) * 25; } public int getcylindrical() { return cylindrical; } public void setcylindrical(String cylindrical) { this.cylindrical = Integer.parseInt(cylindrical); } public float[] getspring() { return spring; } public void setspring(String spring) { String[] split = spring.split(","); this.spring = new float[split.length]; for (int i = 0; i < split.length; i++) { this.spring[i] = Float.parseFloat(split[i]); } } public String gettag() { return tag; } public void settag(String tag) { this.tag = tag; } @Override public String toString() { String str = String.format("%d %d %f %d", startCapped, endCapped, length/25, cylindrical); if (spring != null) { str += " " + spring[0]; for (int i = 1; i < spring.length; i++) { str += "," + spring[i]; } } if (tag != null) { str += " " + tag; } return super.toString(str); } @Override public int parseString(String[] line) { int size = super.parseString(line); setstartCapped(line[size + 1]); setendCapped(line[size + 2]); setlength(line[size + 3]); setcylindrical(line[size + 4]); if (line.length > size + 7) { setspring(line[size + 5]); settag(line[size + 6]); } else if (line.length > size + 6) { if (line[18].contains(",")) { setspring(line[size + 5]); } else { settag(line[size + 5]); } } return 0; } @Override public String getName() { return "Slider"; } @Override public Matrix4 getTransformMatrixForSnapConnecting( Connectivity existingConn, Matrix4 initialTransformOfPart) { Matrix4 newTransform = getRotationMatrixForConnection(existingConn, initialTransformOfPart); if (newTransform != null) { newTransform.translate(initialTransformOfPart.element[3][0], initialTransformOfPart.element[3][1], initialTransformOfPart.element[3][2]); Slider existingSlider = (Slider) existingConn; Vector3f realMatchingPosOfExistingConn = existingConn .getCurrentPos(); Vector3f realPosOfTestingConn = getCurrentPos(newTransform); Vector3f posDifferent = realPosOfTestingConn .sub(realMatchingPosOfExistingConn); Vector3f directionVector = getDirectionVector(newTransform); float endPointOfExsiting = existingSlider.getDirectionVector() .scale(existingSlider.getlength()).dot(directionVector); float minSlidingLength = 0; float maxSlidingLength = getlength(); boolean isSameDirection = false; if (endPointOfExsiting > 0) { isSameDirection = true; minSlidingLength = -(getlength()+existingSlider.getlength()); if (existingSlider.getstartCapped() != 0 || getendCapped() != 0) minSlidingLength = 0; maxSlidingLength = Math.max(existingSlider.getlength(), getlength()); if (getstartCapped() != 0 || existingSlider.getendCapped() != 0) { maxSlidingLength = Math.min(existingSlider.getlength(), getlength()); } } else { minSlidingLength = -(getlength() + existingSlider.getlength()); if (existingSlider.getendCapped() != 0) minSlidingLength = Math.max(minSlidingLength, -existingSlider.getlength()); if (getendCapped() != 0) minSlidingLength = Math.max(minSlidingLength, -getlength()); maxSlidingLength = 0; if (existingSlider.getstartCapped() != 0) { maxSlidingLength = Math.min(maxSlidingLength, -getlength()); } if (getstartCapped() != 0) maxSlidingLength = Math.min(maxSlidingLength, getlength()); } // if start or end capped, restrict the axle sliding. if (maxSlidingLength < minSlidingLength) return null; float projectedDistance = posDifferent.dot(directionVector); float distance = posDifferent.dot(posDifferent) - projectedDistance * projectedDistance; distance = (float) Math.sqrt(distance); if (distance > LDrawGridTypeT.Coarse.getXZValue() * 2) return null; if (projectedDistance >= maxSlidingLength + LDrawGridTypeT.Coarse.getXZValue()) return null; else if (projectedDistance >= maxSlidingLength) projectedDistance = maxSlidingLength; else if (projectedDistance < minSlidingLength - LDrawGridTypeT.Coarse.getXZValue()) return null; else if (projectedDistance < minSlidingLength) projectedDistance = minSlidingLength; Vector3f posAdjust = realMatchingPosOfExistingConn .sub(realPosOfTestingConn); posAdjust = posAdjust.add(directionVector.scale(projectedDistance)); newTransform.translate(posAdjust.x, posAdjust.y, posAdjust.z); // System.out.println("isSameDirection: " + isSameDirection); // System.out.println("Connectible Range: " + minSlidingLength + // ", " // + maxSlidingLength); // System.out.println("ProjectedDistance: " + projectedDistance); } return newTransform; } @Override public Matrix4 getRotationMatrixForConnection(Connectivity existingConn, Matrix4 initialTransformMatrixOfPart) { Matrix4 newMatrix = new Matrix4(initialTransformMatrixOfPart); newMatrix.element[3][0] = newMatrix.element[3][1] = newMatrix.element[3][2] = 0; LDrawPart existingPart = existingConn.getParent(); Matrix4 existingConnTransformMatrix = Matrix4.multiply( existingConn.getTransformMatrix(), existingPart.transformationMatrix()); Matrix4 candidate = Matrix4.multiply(Matrix4.inverse(transformMatrix), existingConnTransformMatrix); for (int i = 0; i < 3; i++) candidate.element[3][i] = 0; Vector3f rotationVector = getRotationVector(candidate); Matrix4 inverseOfCandidate = new Matrix4(candidate); inverseOfCandidate.rotate((float) Math.toRadians(180), rotationVector); Matrix4 initMatrix = new Matrix4(initialTransformMatrixOfPart); for (int i = 0; i < 3; i++) initMatrix.element[3][i] = 0; // System.out.println(getDirectionVector(initMatrix)); // System.out.println(getDirectionVector(candidate)); // System.out.println(getDirectionVector(inverseOfCandidate)); // System.out.println("#####################"); Vector3f directionVector_init = getDirectionVector(initMatrix); Vector3f directionVector_candidate = getDirectionVector(candidate); Vector3f directionVector_icandidate = getDirectionVector(inverseOfCandidate); float dirDiff = (float) Math.acos(directionVector_init .dot(directionVector_candidate) / directionVector_candidate.length() / directionVector_init.length()); float dirDiff2 = (float) Math.acos(directionVector_init .dot(directionVector_icandidate) / directionVector_icandidate.length() / directionVector_init.length()); // System.out.println("#############################"); // System.out.println(Direction6T // .getDirectionOfTransformMatrix(initialTransformMatrixOfPart)); // System.out // .println(Direction6T.getDirectionOfTransformMatrix(candidate)); // System.out.println(Direction6T // .getDirectionOfTransformMatrix(inverseOfCandidate)); // System.out.println("DirectionVectorDiff: " + dirDiff + ", " + dirDiff2); if (directionVector_init.equals(directionVector_candidate)) ; else if (directionVector_init.equals(directionVector_icandidate)) candidate = inverseOfCandidate; else if (dirDiff > dirDiff2) candidate = inverseOfCandidate; ArrayList<Matrix4> candidateForRotation = new ArrayList<Matrix4>(); candidateForRotation.add(candidate); for (int i = 0; i < 1; i++) { candidate = new Matrix4(candidate); candidate.rotate((float) Math.toRadians(180), existingConn.getDirectionVector()); candidateForRotation.add(candidate); } dirDiff = -1; // System.out.println("#########################"); for (Matrix4 matrix : candidateForRotation) { dirDiff2 = matrix .getDifferentValueForRotation(initialTransformMatrixOfPart); if (dirDiff < 0) { dirDiff = dirDiff2; newMatrix = matrix; } else if (dirDiff > dirDiff2 + 0.1f) { dirDiff = dirDiff2; newMatrix = matrix; } } return newMatrix; } @Override public ConnectivityTestResultT isConnectable(IConnectivity connector, Matrix4 partTransformMatrix) { ConnectivityTestResultT result = isConnectable(connector); if (result != ConnectivityTestResultT.True) return result; Matrix4 rotationMatrix = getTransformMatrixForSnapConnecting( connector.getConnectivity(), partTransformMatrix); if (rotationMatrix == null) return ConnectivityTestResultT.False; if (partTransformMatrix.getDefaultTransformPos() .sub(rotationMatrix.getDefaultTransformPos()).length() > 1f) { return ConnectivityTestResultT.False; } return result; } private Vector3f getRotationVector(Matrix4 candidate) { Vector3f directionVector = getDirectionVector(candidate); // System.out.println("DirectionVector: "+directionVector); Vector3f rotationVector = null; switch (Direction6T.getDirectionOfTransformMatrix(Matrix4.multiply( transformMatrix, candidate))) { case X_Minus: case X_Plus: rotationVector = directionVector.cross(new Vector3f(0, 1, 0)); if (rotationVector.equals(new Vector3f())) rotationVector = new Vector3f(0, 1, 0); break; case Y_Minus: case Y_Plus: rotationVector = directionVector.cross(new Vector3f(0, 0, 1)); if (rotationVector.equals(new Vector3f())) rotationVector = new Vector3f(0, 0, 1); break; case Z_Minus: case Z_Plus: rotationVector = directionVector.cross(new Vector3f(1, 0, 0)); if (rotationVector.equals(new Vector3f())) rotationVector = new Vector3f(1, 0, 0); break; } // System.out.println("Rotation Vector: "+rotationVector); return rotationVector; } }